import django_filters
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status, viewsets, filters
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.filters import SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import generics
from course.models import Course
from course.permissions import IsOwnerReadOnly
from course.serializers import CourseSerializer
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication

"""django信号机制自动生成token"""


@receiver(post_save, sender=settings.AUTH_USER_MODEL)  # django的信号机制，post_save在保存之后
def generate_token(sender, instance=None, created=False, **kwargs):
    """创建用户时自动生成Token"""
    if created:
        Token.objects.create(user=instance)


'''1、函数式方式FBV'''


@csrf_exempt
@api_view(["GET", "POST"])
@authentication_classes((BasicAuthentication, SessionAuthentication))  # 1.函数上局部认证，优先级比全局高。注解顺序
def course_list(request):
    """获取所有、新增"""
    if request.method == 'GET':
        s = CourseSerializer(instance=Course.objects.all(), many=True)
        return Response(data=s.data, status=status.HTTP_200_OK)

    elif request.method == 'POST':
        s = CourseSerializer(data=request.data)  # partial部分更新
        if s.is_valid():
            s.save(teacher=request.user)
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(["GET", "PUT", "DELETE"])
def course_detail(request, pk):
    """获取、更新、删除一个"""
    try:
        course = Course.objects.get(pk=pk)
    except Course.DoesNotExist:
        return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
    # else:
    if request.method == "GET":
        s = CourseSerializer(instance=course)
        return Response(data=s.data, status=status.HTTP_200_OK)

    elif request.method == "PUT":
        s = CourseSerializer(instance=course, data=request.data)
        if s.is_valid():
            s.save()
            return Response(data=s.data, status=status.HTTP_200_OK)

    elif request.method == "DELETE":
        course.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


"""2、类视图CBV"""


class CourseList(APIView):
    # 2.类视图里使用局部认证，使用authentication_classes属性
    authentication_classes = (BasicAuthentication, SessionAuthentication, TokenAuthentication)

    def get(self, request):
        queryset = Course.objects.all()
        s = CourseSerializer(instance=queryset, many=True)
        return Response(data=s.data, status=status.HTTP_200_OK)

    def post(self, request):
        s = CourseSerializer(data=request.data)
        if s.is_valid():
            s.save(teacher=self.request.user)
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)


class CourseDetail(APIView):
    @staticmethod
    def get_object(pk):
        try:
            return Course.objects.get(pk=pk)
        except Course.DoesNotExist:
            return None

    def get(self, request, pk):
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj)
        return Response(s.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj, data=request.data)
        if s.is_valid():
            s.save()
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


"""3、通用类视图GCBV"""
"""属性名与方法名不能修改"""


class GCourseList(generics.ListCreateAPIView):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer

    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)


class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsAuthenticated, IsOwnerReadOnly)


"""4、视图集ViewSets"""


class CourseViewSet(viewsets.ModelViewSet):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer

    # 内置过滤器、(模糊搜索，排序)
    filter_backends = [SearchFilter, filters.OrderingFilter]
    search_fields = ['name', 'price', ]
    ordering_fields = ['id']

    # 重写方法，添加teacher字段
    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)
